home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / News / Alexandra.0.82 / Source / parsedate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-30  |  28.0 KB  |  1,076 lines

  1.  
  2. # line 2 "parsedate.y"
  3. /* $Revision: 1.1.1.1 $
  4. **
  5. **  Originally written by Steven M. Bellovin <smb@research.att.com> while
  6. **  at the University of North Carolina at Chapel Hill.  Later tweaked by
  7. **  a couple of people on Usenet.  Completely overhauled by Rich $alz
  8. **  <rsalz@osf.org> and Jim Berets <jberets@bbn.com> in August, 1990.
  9. **  Further revised (removed obsolete constructs and cleaned up timezone
  10. **  names) in August, 1991, by Rich.  Paul Eggert <eggert@twinsun.com>
  11. **  helped in September, 1992.
  12. **
  13. **  This grammar has six shift/reduce conflicts.
  14. **
  15. **  This code is in the public domain and has no copyright.
  16. */
  17. /* SUPPRESS 530 *//* Empty body for statement */
  18. /* SUPPRESS 593 on yyerrlab *//* Label was not used */
  19. /* SUPPRESS 593 on yynewstate *//* Label was not used */
  20. /* SUPPRESS 595 on yypvt *//* Automatic variable may be used before set */
  21. #include <stdio.h>
  22. #include <sys/types.h>
  23. #include <ctype.h>
  24. #include <time.h>
  25.  
  26. #define yyparse        date_parse
  27. #define yylex        date_lex
  28. #define yyerror        date_error
  29.  
  30.  
  31.     /* See the LeapYears table in Convert. */
  32. #define EPOCH        1970
  33. #define END_OF_TIME    2038
  34.     /* Constants for general time calculations. */
  35. #define DST_OFFSET    1
  36. #define SECSPERDAY    (24L * 60L * 60L)
  37.     /* Readability for TABLE stuff. */
  38. #define HOUR(x)        (x * 60)
  39.  
  40. #define LPAREN        '('
  41. #define RPAREN        ')'
  42. #define IS7BIT(x)    ((unsigned int)(x) < 0200)
  43.  
  44. #define SIZEOF(array)    ((int)(sizeof array / sizeof array[0]))
  45. #define ENDOF(array)    (&array[SIZEOF(array)])
  46.  
  47.  
  48. /*
  49. **  An entry in the lexical lookup table.
  50. */
  51. typedef struct _TABLE {
  52.     char    *name;
  53.     int        type;
  54.     time_t    value;
  55. } TABLE;
  56.  
  57. /*
  58. **  Daylight-savings mode:  on, off, or not yet known.
  59. */
  60. typedef enum _DSTMODE {
  61.     DSTon, DSToff, DSTmaybe
  62. } DSTMODE;
  63.  
  64. /*
  65. **  Meridian:  am, pm, or 24-hour style.
  66. */
  67. typedef enum _MERIDIAN {
  68.     MERam, MERpm, MER24
  69. } MERIDIAN;
  70.  
  71.  
  72. /*
  73. **  Global variables.  We could get rid of most of them by using a yacc
  74. **  union, but this is more efficient.  (This routine predates the
  75. **  yacc %union construct.)
  76. */
  77. static char    *yyInput;
  78. static DSTMODE    yyDSTmode;
  79. static int    yyHaveDate;
  80. static int    yyHaveRel;
  81. static int    yyHaveTime;
  82. static time_t    yyTimezone;
  83. static time_t    yyDay;
  84. static time_t    yyHour;
  85. static time_t    yyMinutes;
  86. static time_t    yyMonth;
  87. static time_t    yySeconds;
  88. static time_t    yyYear;
  89. static MERIDIAN    yyMeridian;
  90. static time_t    yyRelMonth;
  91. static time_t    yyRelSeconds;
  92.  
  93.  
  94. extern struct tm    *localtime();
  95.  
  96. static void        date_error();
  97.  
  98. # line 98 "parsedate.y"
  99. typedef union  {
  100.     time_t        Number;
  101.     enum _MERIDIAN    Meridian;
  102. } YYSTYPE;
  103. # define tDAY 257
  104. # define tDAYZONE 258
  105. # define tMERIDIAN 259
  106. # define tMONTH 260
  107. # define tMONTH_UNIT 261
  108. # define tSEC_UNIT 262
  109. # define tSNUMBER 263
  110. # define tUNUMBER 264
  111. # define tZONE 265
  112. #define yyclearin yychar = -1
  113. #define yyerrok yyerrflag = 0
  114. extern int yychar;
  115. extern short yyerrflag;
  116. #ifndef YYMAXDEPTH
  117. #define YYMAXDEPTH 150
  118. #endif
  119. YYSTYPE yylval, yyval;
  120. # define YYERRCODE 256
  121.  
  122. # line 284 "parsedate.y"
  123.  
  124.  
  125. /* Month and day table. */
  126. static TABLE    MonthDayTable[] = {
  127.     { "january",    tMONTH,  1 },
  128.     { "february",    tMONTH,  2 },
  129.     { "march",        tMONTH,  3 },
  130.     { "april",        tMONTH,  4 },
  131.     { "may",        tMONTH,  5 },
  132.     { "june",        tMONTH,  6 },
  133.     { "july",        tMONTH,  7 },
  134.     { "august",        tMONTH,  8 },
  135.     { "september",    tMONTH,  9 },
  136.     { "october",    tMONTH, 10 },
  137.     { "november",    tMONTH, 11 },
  138.     { "december",    tMONTH, 12 },
  139.     /* The value of the day isn't used... */
  140.     { "sunday",        tDAY, 0 },
  141.     { "monday",        tDAY, 0 },
  142.     { "tuesday",    tDAY, 0 },
  143.     { "wednesday",    tDAY, 0 },
  144.     { "thursday",    tDAY, 0 },
  145.     { "friday",        tDAY, 0 },
  146.     { "saturday",    tDAY, 0 },
  147. };
  148.  
  149. /* Time units table. */
  150. static TABLE    UnitsTable[] = {
  151.     { "year",        tMONTH_UNIT,    12 },
  152.     { "month",        tMONTH_UNIT,    1 },
  153.     { "week",        tSEC_UNIT,    7L * 24 * 60 * 60 },
  154.     { "day",        tSEC_UNIT,    1L * 24 * 60 * 60 },
  155.     { "hour",        tSEC_UNIT,    60 * 60 },
  156.     { "minute",        tSEC_UNIT,    60 },
  157.     { "min",        tSEC_UNIT,    60 },
  158.     { "second",        tSEC_UNIT,    1 },
  159.     { "sec",        tSEC_UNIT,    1 },
  160. };
  161.  
  162. /* Timezone table. */
  163. static TABLE    TimezoneTable[] = {
  164.     { "gmt",    tZONE,     HOUR( 0) },    /* Greenwich Mean */
  165.     { "ut",    tZONE,     HOUR( 0) },    /* Universal */
  166.     { "utc",    tZONE,     HOUR( 0) },    /* Universal Coordinated */
  167.     { "cut",    tZONE,     HOUR( 0) },    /* Coordinated Universal */
  168.     { "z",    tZONE,     HOUR( 0) },    /* Greenwich Mean */
  169.     { "wet",    tZONE,     HOUR( 0) },    /* Western European */
  170.     { "bst",    tDAYZONE,  HOUR( 0) },    /* British Summer */
  171.     { "nst",    tZONE,     HOUR(3)+30 }, /* Newfoundland Standard */
  172.     { "ndt",    tDAYZONE,  HOUR(3)+30 }, /* Newfoundland Daylight */
  173.     { "ast",    tZONE,     HOUR( 4) },    /* Atlantic Standard */
  174.     { "adt",    tDAYZONE,  HOUR( 4) },    /* Atlantic Daylight */
  175.     { "est",    tZONE,     HOUR( 5) },    /* Eastern Standard */
  176.     { "edt",    tDAYZONE,  HOUR( 5) },    /* Eastern Daylight */
  177.     { "cst",    tZONE,     HOUR( 6) },    /* Central Standard */
  178.     { "cdt",    tDAYZONE,  HOUR( 6) },    /* Central Daylight */
  179.     { "mst",    tZONE,     HOUR( 7) },    /* Mountain Standard */
  180.     { "mdt",    tDAYZONE,  HOUR( 7) },    /* Mountain Daylight */
  181.     { "pst",    tZONE,     HOUR( 8) },    /* Pacific Standard */
  182.     { "pdt",    tDAYZONE,  HOUR( 8) },    /* Pacific Daylight */
  183.     { "yst",    tZONE,     HOUR( 9) },    /* Yukon Standard */
  184.     { "ydt",    tDAYZONE,  HOUR( 9) },    /* Yukon Daylight */
  185.     { "akst",    tZONE,     HOUR( 9) },    /* Alaska Standard */
  186.     { "akdt",    tDAYZONE,  HOUR( 9) },    /* Alaska Daylight */
  187.     { "hst",    tZONE,     HOUR(10) },    /* Hawaii Standard */
  188.     { "hast",    tZONE,     HOUR(10) },    /* Hawaii-Aleutian Standard */
  189.     { "hadt",    tDAYZONE,  HOUR(10) },    /* Hawaii-Aleutian Daylight */
  190.     { "ces",    tDAYZONE,  -HOUR(1) },    /* Central European Summer */
  191.     { "cest",    tDAYZONE,  -HOUR(1) },    /* Central European Summer */
  192.     { "mez",    tZONE,     -HOUR(1) },    /* Middle European */
  193.     { "mezt",    tDAYZONE,  -HOUR(1) },    /* Middle European Summer */
  194.     { "cet",    tZONE,     -HOUR(1) },    /* Central European */
  195.     { "met",    tZONE,     -HOUR(1) },    /* Middle European */
  196.     { "eet",    tZONE,     -HOUR(2) },    /* Eastern Europe */
  197.     { "msk",    tZONE,     -HOUR(3) },    /* Moscow Winter */
  198.     { "msd",    tDAYZONE,  -HOUR(3) },    /* Moscow Summer */
  199.     { "wast",    tZONE,     -HOUR(8) },    /* West Australian Standard */
  200.     { "wadt",    tDAYZONE,  -HOUR(8) },    /* West Australian Daylight */
  201.     { "hkt",    tZONE,     -HOUR(8) },    /* Hong Kong */
  202.     { "cct",    tZONE,     -HOUR(8) },    /* China Coast */
  203.     { "jst",    tZONE,     -HOUR(9) },    /* Japan Standard */
  204.     { "kst",    tZONE,     -HOUR(9) },    /* Korean Standard */
  205.     { "kdt",    tZONE,     -HOUR(9) },    /* Korean Daylight */
  206.     { "cast",    tZONE,     -(HOUR(9)+30) }, /* Central Australian Standard */
  207.     { "cadt",    tDAYZONE,  -(HOUR(9)+30) }, /* Central Australian Daylight */
  208.     { "east",    tZONE,     -HOUR(10) },    /* Eastern Australian Standard */
  209.     { "eadt",    tDAYZONE,  -HOUR(10) },    /* Eastern Australian Daylight */
  210.     { "nzst",    tZONE,     -HOUR(12) },    /* New Zealand Standard */
  211.     { "nzdt",    tDAYZONE,  -HOUR(12) },    /* New Zealand Daylight */
  212.  
  213.     /* For completeness we include the following entries. */
  214. #if 0
  215.  
  216.     /* Duplicate names.  Either they conflict with a zone listed above
  217.      * (which is either more likely to be seen or just been in circulation
  218.      * longer), or they conflict with another zone in this section and
  219.      * we could not reasonably choose one over the other. */
  220.     { "fst",    tZONE,     HOUR( 2) },    /* Fernando De Noronha Standard */
  221.     { "fdt",    tDAYZONE,  HOUR( 2) },    /* Fernando De Noronha Daylight */
  222.     { "bst",    tZONE,     HOUR( 3) },    /* Brazil Standard */
  223.     { "est",    tZONE,     HOUR( 3) },    /* Eastern Standard (Brazil) */
  224.     { "edt",    tDAYZONE,  HOUR( 3) },    /* Eastern Daylight (Brazil) */
  225.     { "wst",    tZONE,     HOUR( 4) },    /* Western Standard (Brazil) */
  226.     { "wdt",    tDAYZONE,  HOUR( 4) },    /* Western Daylight (Brazil) */
  227.     { "cst",    tZONE,     HOUR( 5) },    /* Chile Standard */
  228.     { "cdt",    tDAYZONE,  HOUR( 5) },    /* Chile Daylight */
  229.     { "ast",    tZONE,     HOUR( 5) },    /* Acre Standard */
  230.     { "adt",    tDAYZONE,  HOUR( 5) },    /* Acre Daylight */
  231.     { "cst",    tZONE,     HOUR( 5) },    /* Cuba Standard */
  232.     { "cdt",    tDAYZONE,  HOUR( 5) },    /* Cuba Daylight */
  233.     { "est",    tZONE,     HOUR( 6) },    /* Easter Island Standard */
  234.     { "edt",    tDAYZONE,  HOUR( 6) },    /* Easter Island Daylight */
  235.     { "sst",    tZONE,     HOUR(11) },    /* Samoa Standard */
  236.     { "ist",    tZONE,     -HOUR(2) },    /* Israel Standard */
  237.     { "idt",    tDAYZONE,  -HOUR(2) },    /* Israel Daylight */
  238.     { "idt",    tDAYZONE,  -(HOUR(3)+30) }, /* Iran Daylight */
  239.     { "ist",    tZONE,     -(HOUR(3)+30) }, /* Iran Standard */
  240.     { "cst",     tZONE,     -HOUR(8) },    /* China Standard */
  241.     { "cdt",     tDAYZONE,  -HOUR(8) },    /* China Daylight */
  242.     { "sst",     tZONE,     -HOUR(8) },    /* Singapore Standard */
  243.  
  244.     /* Dubious (e.g., not in Olson's TIMEZONE package) or obsolete. */
  245.     { "gst",    tZONE,     HOUR( 3) },    /* Greenland Standard */
  246.     { "wat",    tZONE,     -HOUR(1) },    /* West Africa */
  247.     { "at",    tZONE,     HOUR( 2) },    /* Azores */
  248.     { "gst",    tZONE,     -HOUR(10) },    /* Guam Standard */
  249.     { "nft",    tZONE,     HOUR(3)+30 }, /* Newfoundland */
  250.     { "idlw",    tZONE,     HOUR(12) },    /* International Date Line West */
  251.     { "mewt",    tZONE,     -HOUR(1) },    /* Middle European Winter */
  252.     { "mest",    tDAYZONE,  -HOUR(1) },    /* Middle European Summer */
  253.     { "swt",    tZONE,     -HOUR(1) },    /* Swedish Winter */
  254.     { "sst",    tDAYZONE,  -HOUR(1) },    /* Swedish Summer */
  255.     { "fwt",    tZONE,     -HOUR(1) },    /* French Winter */
  256.     { "fst",    tDAYZONE,  -HOUR(1) },    /* French Summer */
  257.     { "bt",    tZONE,     -HOUR(3) },    /* Baghdad */
  258.     { "it",    tZONE,     -(HOUR(3)+30) }, /* Iran */
  259.     { "zp4",    tZONE,     -HOUR(4) },    /* USSR Zone 3 */
  260.     { "zp5",    tZONE,     -HOUR(5) },    /* USSR Zone 4 */
  261.     { "ist",    tZONE,     -(HOUR(5)+30) }, /* Indian Standard */
  262.     { "zp6",    tZONE,     -HOUR(6) },    /* USSR Zone 5 */
  263.     { "nst",    tZONE,     -HOUR(7) },    /* North Sumatra */
  264.     { "sst",    tZONE,     -HOUR(7) },    /* South Sumatra */
  265.     { "jt",    tZONE,     -(HOUR(7)+30) }, /* Java (3pm in Cronusland!) */
  266.     { "nzt",    tZONE,     -HOUR(12) },    /* New Zealand */
  267.     { "idle",    tZONE,     -HOUR(12) },    /* International Date Line East */
  268.     { "cat",    tZONE,     HOUR(10) },    /* -- expired 1967 */
  269.     { "nt",    tZONE,     HOUR(11) },    /* -- expired 1967 */
  270.     { "ahst",    tZONE,     HOUR(10) },    /* -- expired 1983 */
  271.     { "hdt",    tDAYZONE,  HOUR(10) },    /* -- expired 1986 */
  272. #endif /* 0 */
  273. };
  274.  
  275.  
  276. /* ARGSUSED */
  277. static void
  278. date_error(s)
  279.     char    *s;
  280. {
  281.     /* NOTREACHED */
  282. }
  283.  
  284.  
  285. static time_t
  286. ToSeconds(Hours, Minutes, Seconds, Meridian)
  287.     time_t    Hours;
  288.     time_t    Minutes;
  289.     time_t    Seconds;
  290.     MERIDIAN    Meridian;
  291. {
  292.     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 61)
  293.     return -1;
  294.     if (Meridian == MER24) {
  295.     if (Hours < 0 || Hours > 23)
  296.         return -1;
  297.     }
  298.     else {
  299.     if (Hours < 1 || Hours > 12)
  300.         return -1;
  301.     if (Hours == 12)
  302.         Hours = 0;
  303.     if (Meridian == MERpm)
  304.         Hours += 12;
  305.     }
  306.     return (Hours * 60L + Minutes) * 60L + Seconds;
  307. }
  308.  
  309.  
  310. static time_t
  311. Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, dst)
  312.     time_t    Month;
  313.     time_t    Day;
  314.     time_t    Year;
  315.     time_t    Hours;
  316.     time_t    Minutes;
  317.     time_t    Seconds;
  318.     MERIDIAN    Meridian;
  319.     DSTMODE    dst;
  320. {
  321.     static int    DaysNormal[13] = {
  322.     0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  323.     };
  324.     static int    DaysLeap[13] = {
  325.     0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  326.     };
  327.     static int    LeapYears[] = {
  328.     1972, 1976, 1980, 1984, 1988, 1992, 1996,
  329.     2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036
  330.     };
  331.     register int    *yp;
  332.     register int    *mp;
  333.     register time_t    Julian;
  334.     register int    i;
  335.     time_t        tod;
  336.  
  337.     if (Year < 0)
  338.     Year = -Year;
  339.     if (Year < 100)
  340.     Year += 1900;
  341.     if (Year < EPOCH)
  342.     Year += 100;
  343.     for (mp = DaysNormal, yp = LeapYears; yp < ENDOF(LeapYears); yp++)
  344.     if (Year == *yp) {
  345.         mp = DaysLeap;
  346.         break;
  347.     }
  348.     if (Year < EPOCH || Year > END_OF_TIME
  349.      || Month < 1 || Month > 12
  350.      /* NOSTRICT *//* conversion from long may lose accuracy */
  351.      || Day < 1 || Day > mp[(int)Month])
  352.     return -1;
  353.  
  354.     Julian = Day - 1 + (Year - EPOCH) * 365;
  355.     for (yp = LeapYears; yp < ENDOF(LeapYears); yp++, Julian++)
  356.     if (Year <= *yp)
  357.         break;
  358.     for (i = 1; i < Month; i++)
  359.     Julian += *++mp;
  360.     Julian *= SECSPERDAY;
  361.     Julian += yyTimezone * 60L;
  362.     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
  363.     return -1;
  364.     Julian += tod;
  365.     tod = Julian;
  366.     if (dst == DSTon || (dst == DSTmaybe && localtime(&tod)->tm_isdst))
  367.     Julian -= DST_OFFSET * 60L * 60L;
  368.     return Julian;
  369. }
  370.  
  371.  
  372. static time_t
  373. DSTcorrect(Start, Future)
  374.     time_t    Start;
  375.     time_t    Future;
  376. {
  377.     time_t    StartDay;
  378.     time_t    FutureDay;
  379.  
  380.     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
  381.     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
  382.     return (Future - Start) + (StartDay - FutureDay) * DST_OFFSET * 60L * 60L;
  383. }
  384.  
  385.  
  386. static time_t
  387. RelativeMonth(Start, RelMonth)
  388.     time_t    Start;
  389.     time_t    RelMonth;
  390. {
  391.     struct tm    *tm;
  392.     time_t    Month;
  393.     time_t    Year;
  394.  
  395.     tm = localtime(&Start);
  396.     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
  397.     Year = Month / 12;
  398.     Month = Month % 12 + 1;
  399.     return DSTcorrect(Start,
  400.         Convert(Month, (time_t)tm->tm_mday, Year,
  401.         (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
  402.         MER24, DSTmaybe));
  403. }
  404.  
  405.  
  406. static int
  407. LookupWord(buff, length)
  408.     char        *buff;
  409.     register int    length;
  410. {
  411.     register char    *p;
  412.     register char    *q;
  413.     register TABLE    *tp;
  414.     register int    c;
  415.  
  416.     p = buff;
  417.     c = p[0];
  418.  
  419.     /* See if we have an abbreviation for a month. */
  420.     if (length == 3 || (length == 4 && p[3] == '.'))
  421.     for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++) {
  422.         q = tp->name;
  423.         if (c == q[0] && p[1] == q[1] && p[2] == q[2]) {
  424.         yylval.Number = tp->value;
  425.         return tp->type;
  426.         }
  427.     }
  428.     else
  429.     for (tp = MonthDayTable; tp < ENDOF(MonthDayTable); tp++)
  430.         if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
  431.         yylval.Number = tp->value;
  432.         return tp->type;
  433.         }
  434.  
  435.     /* Try for a timezone. */
  436.     for (tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
  437.     if (c == tp->name[0] && p[1] == tp->name[1]
  438.      && strcmp(p, tp->name) == 0) {
  439.         yylval.Number = tp->value;
  440.         return tp->type;
  441.     }
  442.  
  443.     /* Try the units table. */
  444.     for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
  445.     if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
  446.         yylval.Number = tp->value;
  447.         return tp->type;
  448.     }
  449.  
  450.     /* Strip off any plural and try the units table again. */
  451.     if (--length > 0 && p[length] == 's') {
  452.     p[length] = '\0';
  453.     for (tp = UnitsTable; tp < ENDOF(UnitsTable); tp++)
  454.         if (c == tp->name[0] && strcmp(p, tp->name) == 0) {
  455.         p[length] = 's';
  456.         yylval.Number = tp->value;
  457.         return tp->type;
  458.         }
  459.     p[length] = 's';
  460.     }
  461.     length++;
  462.  
  463.     /* Drop out any periods. */
  464.     for (p = buff, q = (char*)buff; *q; q++)
  465.     if (*q != '.')
  466.         *p++ = *q;
  467.     *p = '\0';
  468.  
  469.     /* Try the meridians. */
  470.     if (buff[1] == 'm' && buff[2] == '\0') {
  471.     if (buff[0] == 'a') {
  472.         yylval.Meridian = MERam;
  473.         return tMERIDIAN;
  474.     }
  475.     if (buff[0] == 'p') {
  476.         yylval.Meridian = MERpm;
  477.         return tMERIDIAN;
  478.     }
  479.     }
  480.  
  481.     /* If we saw any periods, try the timezones again. */
  482.     if (p - buff != length) {
  483.     c = buff[0];
  484.     for (p = buff, tp = TimezoneTable; tp < ENDOF(TimezoneTable); tp++)
  485.         if (c == tp->name[0] && p[1] == tp->name[1]
  486.         && strcmp(p, tp->name) == 0) {
  487.         yylval.Number = tp->value;
  488.         return tp->type;
  489.         }
  490.     }
  491.  
  492.     /* Unknown word -- assume GMT timezone. */
  493.     yylval.Number = 0;
  494.     return tZONE;
  495. }
  496.  
  497.  
  498. int
  499. date_lex()
  500. {
  501.     register char    c;
  502.     register char    *p;
  503.     char        buff[20];
  504.     register int    sign;
  505.     register int    i;
  506.     register int    nesting;
  507.  
  508.     for ( ; ; ) {
  509.     /* Get first character after the whitespace. */
  510.     for ( ; ; ) {
  511.         while (isspace(*yyInput))
  512.         yyInput++;
  513.         c = *yyInput;
  514.  
  515.         /* Ignore RFC 822 comments, typically time zone names. */
  516.         if (c != LPAREN)
  517.         break;
  518.         for (nesting = 1; (c = *++yyInput) != RPAREN || --nesting; )
  519.         if (c == LPAREN)
  520.             nesting++;
  521.         else if (!IS7BIT(c) || c == '\0' || c == '\r'
  522.              || (c == '\\' && ((c = *++yyInput) == '\0' || !IS7BIT(c))))
  523.             /* Lexical error: bad comment. */
  524.             return '?';
  525.         yyInput++;
  526.     }
  527.  
  528.     /* A number? */
  529.     if (isdigit(c) || c == '-' || c == '+') {
  530.         if (c == '-' || c == '+') {
  531.         sign = c == '-' ? -1 : 1;
  532.         yyInput++;
  533.         if (!isdigit(*yyInput))
  534.             /* Skip the plus or minus sign. */
  535.             continue;
  536.         }
  537.         else
  538.         sign = 0;
  539.         for (i = 0; (c = *yyInput++) != '\0' && isdigit(c); )
  540.         i = 10 * i + c - '0';
  541.         yyInput--;
  542.         yylval.Number = sign < 0 ? -i : i;
  543.         return sign ? tSNUMBER : tUNUMBER;
  544.     }
  545.  
  546.     /* A word? */
  547.     if (isalpha(c)) {
  548.         for (p = buff; (c = *yyInput++) == '.' || isalpha(c); )
  549.         if (p < &buff[sizeof buff - 1])
  550.             *p++ = isupper(c) ? tolower(c) : c;
  551.         *p = '\0';
  552.         yyInput--;
  553.         return LookupWord(buff, p - buff);
  554.     }
  555.  
  556.     return *yyInput++;
  557.     }
  558. }
  559.  
  560.  
  561. time_t
  562. parsedate(p)
  563.     char        *p;
  564. {
  565.     extern int        date_parse();
  566.     time_t        Start;
  567.  
  568.     yyInput = p;
  569.  
  570.     yyYear = 0;
  571.     yyMonth = 0;
  572.     yyDay = 0;
  573.     yyTimezone = 0;
  574.     yyDSTmode = DSTmaybe;
  575.     yyHour = 0;
  576.     yyMinutes = 0;
  577.     yySeconds = 0;
  578.     yyMeridian = MER24;
  579.     yyRelSeconds = 0;
  580.     yyRelMonth = 0;
  581.     yyHaveDate = 0;
  582.     yyHaveRel = 0;
  583.     yyHaveTime = 0;
  584.  
  585.     if (date_parse() || yyHaveTime > 1 || yyHaveDate > 1)
  586.     return -1;
  587.  
  588.     if (yyHaveDate || yyHaveTime) {
  589.     Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
  590.             yyMeridian, yyDSTmode);
  591.     if (Start < 0)
  592.         return -1;
  593.     }
  594.     else
  595.     return -1;
  596.  
  597.     Start += yyRelSeconds;
  598.     if (yyRelMonth)
  599.     Start += RelativeMonth(Start, yyRelMonth);
  600.  
  601.     /* Have to do *something* with a legitimate -1 so it's distinguishable
  602.      * from the error return value.  (Alternately could set errno on error.) */
  603.     return Start == -1 ? 0 : Start;
  604. }
  605.  
  606.  
  607. #ifdef TEST
  608.  
  609. #if YYDEBUG
  610. extern int    yydebug;
  611. #endif /* YYDEBUG */
  612.  
  613. /* ARGSUSED */
  614. int
  615. main(ac, av)
  616.     int        ac;
  617.     char    *av[];
  618. {
  619.     char    buff[128];
  620.     time_t    d;
  621.  
  622. #if YYDEBUG
  623.     yydebug = 1;
  624. #endif /* YYDEBUG */
  625.  
  626.     (void)printf("Enter date, or blank line to exit.\n\t> ");
  627.     for ( ; ; ) {
  628.     (void)printf("\t> ");
  629.     (void)fflush(stdout);
  630.     if (gets(buff) == NULL || buff[0] == '\n')
  631.         break;
  632. #if YYDEBUG
  633.     if (strcmp(buff, "yydebug") == 0) {
  634.         yydebug = !yydebug;
  635.         printf("yydebug = %s\n", yydebug ? "on" : "off");
  636.         continue;
  637.     }
  638. #endif /* YYDEBUG */
  639.     d = parsedate(buff);
  640.     if (d == -1)
  641.         (void)printf("Bad format - couldn't convert.\n");
  642.     else
  643.         (void)printf("%s", ctime(&d));
  644.     }
  645.  
  646.     exit(0);
  647.     /* NOTREACHED */
  648. }
  649. #endif /* TEST */
  650. short yyexca[] ={
  651. -1, 1,
  652.     0, -1,
  653.     -2, 0,
  654.     };
  655. # define YYNPROD 30
  656. # define YYLAST 216
  657. short yyact[]={
  658.  
  659.   17,  12,  34,  40,  39,  21,  14,   8,  11,  14,
  660.    7,  16,  38,   9,   6,  36,  31,  29,  28,  27,
  661.   22,  14,  25,  24,  37,  35,  30,  23,  13,  15,
  662.    5,   4,   3,   2,   1,  10,   0,   0,   0,   0,
  663.   26,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  664.    0,   0,   0,   0,   0,   0,  33,  32,   0,   0,
  665.    0,   0,   0,   0,   0,   0,   0,  42,  41,   0,
  666.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  667.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  668.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  669.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  670.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  671.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  672.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  673.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  674.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  675.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  676.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  677.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  678.    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
  679.    0,   0,   0,  21,   0,   0,   0,  14,   0,   0,
  680.    0,   0,  21,  18,  20,  19 };
  681. short yypact[]={
  682.  
  683. -1000,-250,-1000,-257,-1000,-1000, -47,-244, -17,-239,
  684. -1000,-242,-1000,-1000,-1000,-1000,-245,-246,-247,-1000,
  685. -1000,-1000, -18,-248,-1000,-1000,-1000, -56, -22,-1000,
  686. -249,-236,-1000,-1000,-252,-260,-1000,-261,-254,-1000,
  687. -1000,-1000,-1000 };
  688. short yypgo[]={
  689.  
  690.    0,  28,  35,  29,  34,  33,  32,  31,  30 };
  691. short yyr1[]={
  692.  
  693.    0,   4,   4,   5,   5,   5,   5,   6,   6,   6,
  694.    6,   6,   2,   2,   2,   2,   1,   7,   7,   7,
  695.    7,   7,   7,   7,   8,   8,   8,   8,   3,   3 };
  696. short yyr2[]={
  697.  
  698.    0,   0,   2,   1,   2,   1,   1,   2,   4,   4,
  699.    6,   6,   1,   1,   2,   1,   1,   3,   5,   2,
  700.    4,   2,   3,   5,   2,   2,   2,   2,   0,   1 };
  701. short yychk[]={
  702.  
  703. -1000,  -4,  -5,  -6,  -7,  -8, 264, 260, 257, 263,
  704.   -2, 265, 258,  -1, 263,  -3,  58,  47, 260, 262,
  705.  261, 259, 264,  44, 262, 261,  -1, 264, 264, 264,
  706.   44, 264,  -3,  -1,  58,  47, 264, 260, 264, 264,
  707.  264,  -3,  -1 };
  708. short yydef[]={
  709.  
  710.    1,  -2,   2,   3,   5,   6,  28,   0,   0,   0,
  711.    4,  12,  13,  15,  16,   7,   0,   0,  21,  25,
  712.   27,  29,  19,   0,  24,  26,  14,  28,  17,  22,
  713.    0,   0,   8,   9,   0,   0,  20,   0,  28,  18,
  714.   23,  10,  11 };
  715. # line 1 "/usr/lib/yaccpar"
  716.  
  717.  
  718. # define YYFLAG -1000
  719. # define YYERROR goto yyerrlab
  720. # define YYACCEPT return(0)
  721. # define YYABORT return(1)
  722.  
  723. /*    parser for yacc output    */
  724.  
  725. #ifdef YYDEBUG
  726. int yydebug = 0; /* 1 for debugging */
  727. #endif
  728. YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
  729. int yychar = -1; /* current input token number */
  730. int yynerrs = 0;  /* number of errors */
  731. short yyerrflag = 0;  /* error recovery flag */
  732.  
  733. int yyparse() {
  734.  
  735.     short yys[YYMAXDEPTH];
  736.     short yyj, yym;
  737.     register YYSTYPE *yypvt;
  738.     register short yystate, *yyps, yyn;
  739.     register YYSTYPE *yypv;
  740.     register short *yyxi;
  741.  
  742.     yystate = 0;
  743.     yychar = -1;
  744.     yynerrs = 0;
  745.     yyerrflag = 0;
  746.     yyps= &yys[-1];
  747.     yypv= &yyv[-1];
  748.  
  749.  yystack:    /* put a state and value onto the stack */
  750.  
  751. #ifdef YYDEBUG
  752.     if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
  753. #endif
  754.         if( ++yyps>= &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
  755.         *yyps = yystate;
  756.         ++yypv;
  757.         *yypv = yyval;
  758.  
  759.  yynewstate:
  760.  
  761.     yyn = yypact[yystate];
  762.  
  763.     if( yyn<= YYFLAG ) goto yydefault; /* simple state */
  764.  
  765.     if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
  766.     if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
  767.  
  768.     if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
  769.         yychar = -1;
  770.         yyval = yylval;
  771.         yystate = yyn;
  772.         if( yyerrflag > 0 ) --yyerrflag;
  773.         goto yystack;
  774.         }
  775.  
  776.  yydefault:
  777.     /* default state action */
  778.  
  779.     if( (yyn=yydef[yystate]) == -2 ) {
  780.         if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
  781.         /* look through exception table */
  782.  
  783.         for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
  784.  
  785.         while( *(yyxi+=2) >= 0 ){
  786.             if( *yyxi == yychar ) break;
  787.             }
  788.         if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
  789.         }
  790.  
  791.     if( yyn == 0 ){ /* error */
  792.         /* error ... attempt to resume parsing */
  793.  
  794.         switch( yyerrflag ){
  795.  
  796.         case 0:   /* brand new error */
  797.  
  798.             yyerror( "syntax error" );
  799.         
  800.             ++yynerrs;
  801.  
  802.         case 1:
  803.         case 2: /* incompletely recovered error ... try again */
  804.  
  805.             yyerrflag = 3;
  806.  
  807.             /* find a state where "error" is a legal shift action */
  808.  
  809.             while ( yyps >= yys ) {
  810.                yyn = yypact[*yyps] + YYERRCODE;
  811.                if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
  812.                   yystate = yyact[yyn];  /* simulate a shift of "error" */
  813.                   goto yystack;
  814.                   }
  815.                yyn = yypact[*yyps];
  816.  
  817.                /* the current yyps has no shift onn "error", pop stack */
  818.  
  819. #ifdef YYDEBUG
  820.                if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
  821. #endif
  822.                --yyps;
  823.                --yypv;
  824.                }
  825.  
  826.             /* there is no state on the stack with an error shift ... abort */
  827.  
  828.     yyabort:
  829.             return(1);
  830.  
  831.  
  832.         case 3:  /* no shift yet; clobber input char */
  833.  
  834. #ifdef YYDEBUG
  835.             if( yydebug ) printf( "error recovery discards char %d\n", yychar );
  836. #endif
  837.  
  838.             if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
  839.             yychar = -1;
  840.             goto yynewstate;   /* try again in the same state */
  841.  
  842.             }
  843.  
  844.         }
  845.  
  846.     /* reduction by production yyn */
  847.  
  848. #ifdef YYDEBUG
  849.         if( yydebug ) printf("reduce %d\n",yyn);
  850. #endif
  851.         yyps -= yyr2[yyn];
  852.         yypvt = yypv;
  853.         yypv -= yyr2[yyn];
  854.         yyval = yypv[1];
  855.         yym=yyn;
  856.             /* consult goto table to find next state */
  857.         yyn = yyr1[yyn];
  858.         yyj = yypgo[yyn] + *yyps + 1;
  859.         if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
  860.         switch(yym){
  861.             
  862. case 3:
  863. # line 116 "parsedate.y"
  864. {
  865.         yyHaveTime++;
  866. #ifdef lint
  867.         /* I am compulsive about lint natterings... */
  868.         if (yyHaveTime == -1) {
  869.         YYERROR;
  870.         }
  871. #endif /* lint */
  872.     } break;
  873. case 4:
  874. # line 125 "parsedate.y"
  875. {
  876.         yyHaveTime++;
  877.         yyTimezone = yypvt[-0].Number;
  878.     } break;
  879. case 5:
  880. # line 129 "parsedate.y"
  881. {
  882.         yyHaveDate++;
  883.     } break;
  884. case 6:
  885. # line 132 "parsedate.y"
  886. {
  887.         yyHaveRel = 1;
  888.     } break;
  889. case 7:
  890. # line 137 "parsedate.y"
  891. {
  892.         if (yypvt[-1].Number < 100) {
  893.         yyHour = yypvt[-1].Number;
  894.         yyMinutes = 0;
  895.         }
  896.         else {
  897.         yyHour = yypvt[-1].Number / 100;
  898.         yyMinutes = yypvt[-1].Number % 100;
  899.         }
  900.         yySeconds = 0;
  901.         yyMeridian = yypvt[-0].Meridian;
  902.     } break;
  903. case 8:
  904. # line 149 "parsedate.y"
  905. {
  906.         yyHour = yypvt[-3].Number;
  907.         yyMinutes = yypvt[-1].Number;
  908.         yySeconds = 0;
  909.         yyMeridian = yypvt[-0].Meridian;
  910.     } break;
  911. case 9:
  912. # line 155 "parsedate.y"
  913. {
  914.         yyHour = yypvt[-3].Number;
  915.         yyMinutes = yypvt[-1].Number;
  916.         yyTimezone = yypvt[-0].Number;
  917.         yyMeridian = MER24;
  918.         yyDSTmode = DSToff;
  919.     } break;
  920. case 10:
  921. # line 162 "parsedate.y"
  922. {
  923.         yyHour = yypvt[-5].Number;
  924.         yyMinutes = yypvt[-3].Number;
  925.         yySeconds = yypvt[-1].Number;
  926.         yyMeridian = yypvt[-0].Meridian;
  927.     } break;
  928. case 11:
  929. # line 168 "parsedate.y"
  930. {
  931.         yyHour = yypvt[-5].Number;
  932.         yyMinutes = yypvt[-3].Number;
  933.         yySeconds = yypvt[-1].Number;
  934.         yyTimezone = yypvt[-0].Number;
  935.         yyMeridian = MER24;
  936.         yyDSTmode = DSToff;
  937.     } break;
  938. case 12:
  939. # line 178 "parsedate.y"
  940. {
  941.         yyval.Number = yypvt[-0].Number;
  942.         yyDSTmode = DSToff;
  943.     } break;
  944. case 13:
  945. # line 182 "parsedate.y"
  946. {
  947.         yyval.Number = yypvt[-0].Number;
  948.         yyDSTmode = DSTon;
  949.     } break;
  950. case 14:
  951. # line 186 "parsedate.y"
  952. {
  953.         /* Only allow "GMT+300" and "GMT-0800" */
  954.         if (yypvt[-1].Number != 0) {
  955.         YYABORT;
  956.         }
  957.         yyval.Number = yypvt[-0].Number;
  958.         yyDSTmode = DSToff;
  959.     } break;
  960. case 15:
  961. # line 194 "parsedate.y"
  962. {
  963.         yyval.Number = yypvt[-0].Number;
  964.         yyDSTmode = DSToff;
  965.     } break;
  966. case 16:
  967. # line 200 "parsedate.y"
  968. {
  969.         int        i;
  970.  
  971.         /* Unix and GMT and numeric timezones -- a little confusing. */
  972.         if (yypvt[-0].Number < 0) {
  973.         /* Don't work with negative modulus. */
  974.         yypvt[-0].Number = -yypvt[-0].Number;
  975.         if (yypvt[-0].Number > 9999 || (i = yypvt[-0].Number % 100) >= 60) {
  976.             YYABORT;
  977.         }
  978.         yyval.Number = (yypvt[-0].Number / 100) * 60 + i;
  979.         }
  980.         else {
  981.         if (yypvt[-0].Number > 9999 || (i = yypvt[-0].Number % 100) >= 60) {
  982.             YYABORT;
  983.         }
  984.         yyval.Number = -((yypvt[-0].Number / 100) * 60 + i);
  985.         }
  986.     } break;
  987. case 17:
  988. # line 221 "parsedate.y"
  989. {
  990.         yyMonth = yypvt[-2].Number;
  991.         yyDay = yypvt[-0].Number;
  992.     } break;
  993. case 18:
  994. # line 225 "parsedate.y"
  995. {
  996.         if (yypvt[-4].Number > 100) {
  997.         yyYear = yypvt[-4].Number;
  998.         yyMonth = yypvt[-2].Number;
  999.         yyDay = yypvt[-0].Number;
  1000.         }
  1001.         else {
  1002.         yyMonth = yypvt[-4].Number;
  1003.         yyDay = yypvt[-2].Number;
  1004.         yyYear = yypvt[-0].Number;
  1005.         }
  1006.     } break;
  1007. case 19:
  1008. # line 237 "parsedate.y"
  1009. {
  1010.         yyMonth = yypvt[-1].Number;
  1011.         yyDay = yypvt[-0].Number;
  1012.     } break;
  1013. case 20:
  1014. # line 241 "parsedate.y"
  1015. {
  1016.         yyMonth = yypvt[-3].Number;
  1017.         yyDay = yypvt[-2].Number;
  1018.         yyYear = yypvt[-0].Number;
  1019.     } break;
  1020. case 21:
  1021. # line 246 "parsedate.y"
  1022. {
  1023.         yyDay = yypvt[-1].Number;
  1024.         yyMonth = yypvt[-0].Number;
  1025.     } break;
  1026. case 22:
  1027. # line 250 "parsedate.y"
  1028. {
  1029.         yyDay = yypvt[-2].Number;
  1030.         yyMonth = yypvt[-1].Number;
  1031.         yyYear = yypvt[-0].Number;
  1032.     } break;
  1033. case 23:
  1034. # line 255 "parsedate.y"
  1035. {
  1036.         yyDay = yypvt[-2].Number;
  1037.         yyMonth = yypvt[-1].Number;
  1038.         yyYear = yypvt[-0].Number;
  1039.     } break;
  1040. case 24:
  1041. # line 262 "parsedate.y"
  1042. {
  1043.         yyRelSeconds += yypvt[-1].Number * yypvt[-0].Number;
  1044.     } break;
  1045. case 25:
  1046. # line 265 "parsedate.y"
  1047. {
  1048.         yyRelSeconds += yypvt[-1].Number * yypvt[-0].Number;
  1049.     } break;
  1050. case 26:
  1051. # line 268 "parsedate.y"
  1052. {
  1053.         yyRelMonth += yypvt[-1].Number * yypvt[-0].Number;
  1054.     } break;
  1055. case 27:
  1056. # line 271 "parsedate.y"
  1057. {
  1058.         yyRelMonth += yypvt[-1].Number * yypvt[-0].Number;
  1059.     } break;
  1060. case 28:
  1061. # line 276 "parsedate.y"
  1062. {
  1063.         yyval.Meridian = MER24;
  1064.     } break;
  1065. case 29:
  1066. # line 279 "parsedate.y"
  1067. {
  1068.         yyval.Meridian = yypvt[-0].Meridian;
  1069.     } break;
  1070. # line 148 "/usr/lib/yaccpar"
  1071.  
  1072.         }
  1073.         goto yystack;  /* stack new state and value */
  1074.  
  1075.     }
  1076.